package com.zzyl.nursing.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.common.core.page.TableDataInfo;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.UserThreadLocal;
import com.zzyl.nursing.domain.Reservation;
import com.zzyl.nursing.dto.ReservationDto;
import com.zzyl.nursing.mapper.ReservationMapper;
import com.zzyl.nursing.service.IMemberReservationService;
import com.zzyl.nursing.vo.TimeCountVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;


@Service
@Slf4j
public class MemberReservationServiceImpl extends ServiceImpl<ReservationMapper, Reservation> implements IMemberReservationService {

    @Autowired
    private ReservationMapper reservationMapper;
    // 假设每个时间段的最大预约次数为6
    private static final int MAX_RESERVATION_COUNT = 6;
    // 时间格式化器，用于将LocalDateTime转换为字符串
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 查询用户在指定时间段内取消的预约数量
     *
     * @param userId
     * @param startTime
     * @param endTime
     * @return
     */
    @Override
    public int countCancelledByUserAndTime(Long userId, LocalDateTime startTime, LocalDateTime endTime) {
        int count = reservationMapper.selectcountCancelledByUserAndTime(userId, startTime, endTime);
        return count;
    }

    /**
     * 查询指定日期各时间段剩余预约次数
     *
     * @param time 日期时间戳
     * @return 各时间段剩余预约次数列表
     */
    @Override
    public List<TimeCountVo> countRemainingByTime(long time) {
        // 将时间戳转换为LocalDateTime - 使用完整的类名或正确导入
        LocalDateTime dateTime = LocalDateTimeUtil.of(time);
        LocalDate targetDate = dateTime.toLocalDate();

        // 生成所有预约时间段
        List<LocalDateTime> timeSlots = generateTimeSlots(targetDate);

        List<TimeCountVo> result = new ArrayList<>();

        // 计算每个时间段的剩余预约次数
        for (LocalDateTime slot : timeSlots) {
            // 计算当前时间段的结束时间（当前时间+30分钟）
            LocalDateTime slotEnd = slot.plusMinutes(30);

            // 查询该时间段内已预约的数量（状态为0：待报道和1：已完成）
            LambdaQueryWrapper<Reservation> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.ge(Reservation::getTime, slot)
                    .lt(Reservation::getTime, slotEnd)
                    .in(Reservation::getStatus, 0, 1);

            long bookedCount = count(queryWrapper);
            int remainingCount = MAX_RESERVATION_COUNT - (int) bookedCount;

            // 将LocalDateTime转换为String类型，再添加到结果中
            String timeStr = LocalDateTimeUtil.format(slot, TIME_FORMATTER);
            // 只添加剩余次数小于最大次数的时间段
            if (remainingCount < MAX_RESERVATION_COUNT) {
                result.add(new TimeCountVo(timeStr, remainingCount));
            }
        }

        return result;
    }

    /**
     * 插入预约信息
     */
    @Override
    public void insertReservation(ReservationDto reservationDto) {
        if (reservationDto != null) {

            Reservation reservation = new Reservation();
            reservation.setName(reservationDto.getName());
            Long count = lambdaQuery()
                    .eq(Reservation::getMobile, reservationDto.getMobile())
                    .eq(Reservation::getTime, reservationDto.getTime())
                    .count();
            if (count > 0) {
                throw new BaseException("相同时间段一个手机号只能预约一次");
            }
            reservation.setMobile(reservationDto.getMobile());
            reservation.setTime(reservationDto.getTime());
            reservation.setVisitor(reservationDto.getVisitor());
            reservation.setType(reservationDto.getType());
            reservation.setStatus(0);
            reservation.setCreateBy(UserThreadLocal.getUserId().toString());
            save(reservation);
            log.info("插入预约信息成功：{}", reservation);
        }
    }

    /**
     * 查询用户预约列表
     */
    @Override
    public List<Reservation> selectReservationList(Reservation reservation) {

        return reservationMapper.selectReservationList(reservation);
    }

    /**
     * 生成指定日期的所有预约时间段
     * 上午8:00-12:00，下午12:30-18:00，每隔30分钟一个时间段
     */
    private List<LocalDateTime> generateTimeSlots(LocalDate date) {
        List<LocalDateTime> timeSlots = new ArrayList<>();

        // 上午时间段：8:00-12:00，每隔30分钟
        LocalTime morningStart = LocalTime.of(8, 0);  // 8:00
        LocalTime morningEnd = LocalTime.of(12, 0);   // 12:00
        generateSlotsForTimeRange(date, morningStart, morningEnd, timeSlots);

        // 下午时间段：12:30-18:00，每隔30分钟
        LocalTime afternoonStart = LocalTime.of(12, 30);  // 12:30
        LocalTime afternoonEnd = LocalTime.of(18, 0);     // 18:00
        generateSlotsForTimeRange(date, afternoonStart, afternoonEnd, timeSlots);

        return timeSlots;
    }

    /**
     * 生成指定日期和时间范围内的时间段
     */
    private void generateSlotsForTimeRange(LocalDate date, LocalTime start, LocalTime end, List<LocalDateTime> slots) {
        LocalTime current = start;
        while (!current.isAfter(end)) {
            slots.add(LocalDateTime.of(date, current));
            current = current.plusMinutes(30);
        }
    }
}
